package com.unicdata.ai.demo_2af.common.filters;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;

/**
 * @author lhn
 * @date 2025/06/26 09:47
 * @since 1.0.0
 **/
@Slf4j
public class CustomAuthFilter extends FormAuthenticationFilter {

    /**
     * 拦截未登录访问受保护资源时的行为
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        log.info("请求 URI: {}", ((HttpServletRequest) request).getRequestURI());
        Subject subject = getSubject(request, response);

        // 如果是登录请求，继续处理（不拦截）
        if (isLoginRequest(request, response)) {
            return true;
        }

        // 如果已经登录，放行
        if (subject.isAuthenticated()) {
            return true;
        }

        // 未登录，返回 JSON 提示
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        if ("XMLHttpRequest".equalsIgnoreCase(httpRequest.getHeader("X-Requested-With"))) {
            // 前端 Ajax 请求，返回 JSON
            httpResponse.setCharacterEncoding(StandardCharsets.UTF_8.name());
            httpResponse.setContentType("application/json");
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

            PrintWriter out = httpResponse.getWriter();
            ObjectMapper mapper = new ObjectMapper();

            String json = mapper.writeValueAsString(new Response(401, "未登录或会话超时，请重新登录"));
            out.write(json);
            out.flush();
            out.close();

            return false;
        } else {
            // 非 Ajax 请求，走默认重定向逻辑
            saveRequestAndRedirectToLogin(request, response);
            return false;
        }
    }

    // 简单封装一个响应对象
    private static class Response {
        public int code;
        public String message;

        public Response(int code, String message) {
            this.code = code;
            this.message = message;
        }
    }
}